package org.twndmv.it;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.util.List;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.twndmv.bo.Color;
import org.twndmv.bo.Sex;
import org.twndmv.dto.PersonDTO;
import org.twndmv.dto.PhysicalDetailsDTO;
import org.twndmv.dto.VehicleRegistrationDTO;
import org.twndmv.ejb.DmvTestUtilRemote;
import org.twndmv.ejb.PersonMgmtRemote;
import org.twndmv.ejb.VehicleMgmtRemote;

public class VehicleMgmtIT {
	private static Log log = LogFactory.getLog(VehicleMgmtIT.class);
	private Context jndi;

	private static final String dmvVehicleJNDI = System
			.getProperty("jndi.name.vehicle",
					"twnDmvEAR/twnDmvEJB/VehicleMgmtEJB!org.twndmv.ejb.VehicleMgmtRemote");
	private static final String dmvTestUtilJNDI = System
			.getProperty("jndi.name.dmvTestUtil",
					"twnDmvEAR/twnDmvEJB/DmvTestUtilEJB!org.twndmv.ejb.DmvTestUtilRemote");
	private static final String dmvPersonJNDI = System
			.getProperty("jndi.name.person",
					"twnDmvEAR/twnDmvEJB/PersonMgmtEJB!org.twndmv.ejb.PersonMgmtRemote");

	private static final String adminUser = System.getProperty("admin.user",
			"admin1");
	private static final String knownUser = System.getProperty("known.user",
			"known");
	private static final String kathyUser = System.getProperty("kathy.user",
			"kathy");
	private static final String sherriUser = System.getProperty("sherri.user",
			"sherri");
	private static final String raleighUser = System.getProperty(
			"raleigh.user", "sysRaleigh");
	private static final String mayberryUser = System.getProperty(
			"mayberry.user", "sysMayberry");
	private static final String andyUser = System.getProperty("andy.user",
			"andy");
	private static final String barneyUser = System.getProperty("barney.user",
			"barney");
	private static final String gomerUser = System.getProperty("gomer.user",
			"gomer");
	private static final String password = System.getProperty("password",
			"password");

	private DmvTestUtilRemote testUtil;
	private VehicleMgmtRemote vehicleManager;
	private PersonMgmtRemote personManager;

	private Context runAs(String username, String password)
			throws NamingException {
		if (jndi != null) {
			jndi.close();
		}
		Properties env = new Properties();
		if (username != null) {
			env.put(Context.SECURITY_PRINCIPAL, username);
			env.put(Context.SECURITY_CREDENTIALS, password);
		}
		log.debug(String.format("%s env=%s", username == null ? "anonymous"
				: username, env));
		jndi = new InitialContext(env);
		return jndi;
	}

	@Before
	public void setUp() throws Exception {

		jndi = runAs(adminUser, password);
		jndi.lookup("/"); // do a quick comms check of JNDI

		testUtil = (DmvTestUtilRemote) jndi.lookup(dmvTestUtilJNDI);
		vehicleManager = (VehicleMgmtRemote) jndi.lookup(dmvVehicleJNDI);
		personManager = (PersonMgmtRemote) jndi.lookup(dmvPersonJNDI);

		assertNotNull(testUtil);
		assertNotNull(vehicleManager);
		assertNotNull(personManager);
	}

	/**
	 * It is important to close the JNDI context in between tests
	 */
	@After
	public void tearDown() throws NamingException {
		if (jndi != null) {
			jndi.close();
			jndi = null;
		}
	}

	@Test
	public void testVehicleManager() throws NamingException {
		log.info("===== VehicleMgmtIT.testVehicleManager =====");
		testUtil.resetAll();

		jndi = runAs(raleighUser, password);
		PersonDTO testPerson = new PersonDTO();
		testPerson.setFirstName("Steve");
		testPerson.setMiddleName("Danger");
		testPerson.setLastName("Jobs");
		PhysicalDetailsDTO testDetails = new PhysicalDetailsDTO();
		testDetails.setHeight(64);
		testDetails.setWeight(180);
		testDetails.setSEX(Sex.MALE);
		testPerson.setPhysicalDetails(testDetails);
		personManager.createPerson(testPerson);

		VehicleRegistrationDTO newCar = new VehicleRegistrationDTO();
		newCar.setMake("WEIRD");
		newCar.setModel("INTERESTING");
		newCar.setYear(1987);
		newCar.setColor(Color.BRONZE);

		jndi = runAs(mayberryUser, password);
		testPerson = personManager.getPeopleByLastName("Jobs").get(0);
		newCar.getOwners().add(testPerson);
		jndi = runAs(sherriUser, password);
		vehicleManager.addRegistration(newCar);
		jndi = runAs(mayberryUser, password);
		List<VehicleRegistrationDTO> newCars = vehicleManager
				.getRegistrationsByMakeModel("WEIRD", "INTERESTING");
		assertNotNull(newCars);
		assertEquals(1, newCars.size());
		VehicleRegistrationDTO tempCar = newCars.get(0);
		assertEquals(tempCar.getYear(), newCar.getYear());
		assertTrue(tempCar.getColor().getName()
				.equalsIgnoreCase(newCar.getColor().getName()));
		log.info("\n\n\nTest car: " + tempCar.getId() + " - "
				+ tempCar.printSummary());
		testPerson.getRegistrations().add(tempCar);
		jndi = runAs(kathyUser, password);
		personManager.updatePerson(testPerson);

		jndi = runAs(mayberryUser, password);
		List<PersonDTO> peeps = personManager.getPeopleByLastName(testPerson
				.getLastName());
		assertNotNull(peeps);
		assertEquals(1, peeps.size());
		PersonDTO resultPeep = peeps.get(0);
		log.info("\n\n\nTest Person: " + resultPeep.getId() + " - "
				+ resultPeep.printName());

		List<VehicleRegistrationDTO> cars = vehicleManager
				.getRegistrationsByOwner(resultPeep);
		assertNotNull(cars);
		assertEquals(1, cars.size());
		VehicleRegistrationDTO resultCar = cars.get(0);
		assertEquals(resultCar.getYear(), newCar.getYear());
		assertTrue(resultCar.getColor().getName()
				.equalsIgnoreCase(newCar.getColor().getName()));

	}

}
